/**
 ******************************************************************************
 * @file           : bsp_dac.c
 * @brief          : DAC Driver Implementation (STM32F1xx)
 ******************************************************************************
 * @attention
 *
 * DAC驱动程序实现文件
 * 提供双通道DAC输出功能
 * 支持电压输出和波形生成
 *
 ******************************************************************************
 */

/* Includes ------------------------------------------------------------------*/
#include "./BSP/DAC/bsp_dac.h"
#include "./BSP/DAC/bsp_dac_config.h"

/* Private includes ----------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static DAC_HandleTypeDef sg_dac_handle;                     /*!< DAC句柄 */
static volatile uint8_t sg_dac_ch1_initialized = 0;         /*!< 通道1初始化标志 */
static volatile uint8_t sg_dac_ch2_initialized = 0;         /*!< 通道2初始化标志 */

/* Private function prototypes -----------------------------------------------*/
static void dac_gpio_init(DAC_Channel_e channel);
static uint32_t dac_get_hal_channel(DAC_Channel_e channel);

/* Private functions ---------------------------------------------------------*/

/**
 * @brief       DAC GPIO初始化
 *
 * @param[in]   channel DAC通道
 *
 * @retval      无
 *
 * @note        配置DAC输出引脚为模拟输出模式
 */
static void dac_gpio_init(DAC_Channel_e channel)
{
    GPIO_InitTypeDef gpio_init_struct;

    gpio_init_struct.Mode = GPIO_MODE_ANALOG;
    gpio_init_struct.Pull = GPIO_NOPULL;

    if (channel == DAC_CH_1)
    {
        DAC_CH1_GPIO_CLK_ENABLE();
        gpio_init_struct.Pin = DAC_CH1_GPIO_PIN;
        HAL_GPIO_Init(DAC_CH1_GPIO_PORT, &gpio_init_struct);
    }
    else if (channel == DAC_CH_2)
    {
        DAC_CH2_GPIO_CLK_ENABLE();
        gpio_init_struct.Pin = DAC_CH2_GPIO_PIN;
        HAL_GPIO_Init(DAC_CH2_GPIO_PORT, &gpio_init_struct);
    }
}

/**
 * @brief       获取HAL库通道定义
 *
 * @param[in]   channel DAC通道枚举
 *
 * @retval      HAL通道定义
 *
 * @note        内部转换函数
 */
static uint32_t dac_get_hal_channel(DAC_Channel_e channel)
{
    return (channel == DAC_CH_1) ? DAC_CHANNEL_1 : DAC_CHANNEL_2;
}

/* Exported functions --------------------------------------------------------*/

/**
 * @brief       DAC通道初始化
 *
 * @param[in]   channel DAC通道（DAC_CH_1或DAC_CH_2）
 *
 * @retval      无
 *
 * @note        初始化指定DAC通道
 */
void dac_init(DAC_Channel_e channel)
{
    DAC_ChannelConfTypeDef dac_ch_conf = {0};

    if (channel == DAC_CH_1 && sg_dac_ch1_initialized)
    {
        log_w("DAC通道1已经初始化");
        return;
    }

    if (channel == DAC_CH_2 && sg_dac_ch2_initialized)
    {
        log_w("DAC通道2已经初始化");
        return;
    }

    /* 使能DAC时钟 */
    DAC_DACx_CLK_ENABLE();

    /* 初始化GPIO */
    dac_gpio_init(channel);

    /* 配置DAC */
    sg_dac_handle.Instance = DAC_DACx;

    if (HAL_DAC_Init(&sg_dac_handle) != HAL_OK)
    {
        log_e("DAC外设初始化失败");
        return;
    }

    /* 配置DAC通道 */
    dac_ch_conf.DAC_Trigger = DAC_TRIGGER_NONE;                /* 软件触发 */
    dac_ch_conf.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;    /* 使能输出缓冲 */

    if (HAL_DAC_ConfigChannel(&sg_dac_handle, &dac_ch_conf, dac_get_hal_channel(channel)) != HAL_OK)
    {
        log_e("DAC通道配置失败");
        return;
    }

    /* 设置初始化标志 */
    if (channel == DAC_CH_1)
    {
        sg_dac_ch1_initialized = 1;
        log_i("DAC通道1初始化完成");
    }
    else
    {
        sg_dac_ch2_initialized = 1;
        log_i("DAC通道2初始化完成");
    }
}

/**
 * @brief       DAC通道反初始化
 *
 * @param[in]   channel DAC通道
 *
 * @retval      无
 *
 * @note        释放DAC通道资源
 */
void dac_deinit(DAC_Channel_e channel)
{
    if (channel == DAC_CH_1 && !sg_dac_ch1_initialized)
    {
        return;
    }

    if (channel == DAC_CH_2 && !sg_dac_ch2_initialized)
    {
        return;
    }

    /* 停止DAC */
    HAL_DAC_Stop(&sg_dac_handle, dac_get_hal_channel(channel));

    /* 反初始化GPIO */
    if (channel == DAC_CH_1)
    {
        HAL_GPIO_DeInit(DAC_CH1_GPIO_PORT, DAC_CH1_GPIO_PIN);
        sg_dac_ch1_initialized = 0;
        log_i("DAC通道1已反初始化");
    }
    else
    {
        HAL_GPIO_DeInit(DAC_CH2_GPIO_PORT, DAC_CH2_GPIO_PIN);
        sg_dac_ch2_initialized = 0;
        log_i("DAC通道2已反初始化");
    }
}

/**
 * @brief       设置DAC输出值
 *
 * @param[in]   channel DAC通道
 * @param[in]   value   DAC值(0-4095)
 *
 * @retval      DAC_OK         设置成功
 * @retval      DAC_ERROR_PARAM 参数错误
 * @retval      DAC_ERROR_HAL   HAL库错误
 *
 * @note        直接设置DAC数字值
 */
DAC_Error_e dac_set_value(DAC_Channel_e channel, uint16_t value)
{
    /* 参数检查 */
    if (value > DAC_MAX_VALUE)
    {
        log_w("DAC值超出范围: %d", value);
        return DAC_ERROR_PARAM;
    }

    if ((channel == DAC_CH_1 && !sg_dac_ch1_initialized) ||
        (channel == DAC_CH_2 && !sg_dac_ch2_initialized))
    {
        log_e("DAC通道%d未初始化", channel);
        return DAC_ERROR_PARAM;
    }

    /* 设置DAC值 */
    if (HAL_DAC_SetValue(&sg_dac_handle, dac_get_hal_channel(channel), DAC_ALIGN_12B_R, value) != HAL_OK)
    {
        log_e("DAC设置值失败");
        return DAC_ERROR_HAL;
    }

    /* 启动DAC */
    HAL_DAC_Start(&sg_dac_handle, dac_get_hal_channel(channel));

    log_d("DAC通道%d输出: %d", channel, value);
    return DAC_OK;
}

/**
 * @brief       设置DAC输出电压
 *
 * @param[in]   channel DAC通道
 * @param[in]   voltage 电压值(V)，范围0-3.3V
 *
 * @retval      DAC_OK         设置成功
 * @retval      DAC_ERROR_PARAM 参数错误
 * @retval      DAC_ERROR_HAL   HAL库错误
 *
 * @note        自动转换电压为DAC值
 */
DAC_Error_e dac_set_voltage(DAC_Channel_e channel, float voltage)
{
    uint16_t dac_value;

    /* 参数检查 */
    if (voltage < 0.0f || voltage > DAC_VREF)
    {
        log_w("DAC电压超出范围: %.3fV", voltage);
        return DAC_ERROR_PARAM;
    }

    /* 电压转DAC值（使用固定参考电压） */
    dac_value = (uint16_t)(voltage * DAC_MAX_VALUE / DAC_VREF);

    log_d("DAC通道%d输出: %.3fV (DAC=%d)", channel, voltage, dac_value);
    return dac_set_value(channel, dac_value);
}

/**
 * @brief       使能DAC输出
 *
 * @param[in]   channel DAC通道
 *
 * @retval      DAC_OK         使能成功
 * @retval      DAC_ERROR_PARAM 参数错误
 * @retval      DAC_ERROR_HAL   HAL库错误
 *
 * @note        启动DAC输出
 */
DAC_Error_e dac_enable(DAC_Channel_e channel)
{
    if ((channel == DAC_CH_1 && !sg_dac_ch1_initialized) ||
        (channel == DAC_CH_2 && !sg_dac_ch2_initialized))
    {
        log_e("DAC通道%d未初始化", channel);
        return DAC_ERROR_PARAM;
    }

    if (HAL_DAC_Start(&sg_dac_handle, dac_get_hal_channel(channel)) != HAL_OK)
    {
        log_e("DAC使能失败");
        return DAC_ERROR_HAL;
    }

    log_d("DAC通道%d已使能", channel);
    return DAC_OK;
}

/**
 * @brief       禁用DAC输出
 *
 * @param[in]   channel DAC通道
 *
 * @retval      DAC_OK         禁用成功
 * @retval      DAC_ERROR_PARAM 参数错误
 * @retval      DAC_ERROR_HAL   HAL库错误
 *
 * @note        停止DAC输出
 */
DAC_Error_e dac_disable(DAC_Channel_e channel)
{
    if ((channel == DAC_CH_1 && !sg_dac_ch1_initialized) ||
        (channel == DAC_CH_2 && !sg_dac_ch2_initialized))
    {
        return DAC_ERROR_PARAM;
    }

    if (HAL_DAC_Stop(&sg_dac_handle, dac_get_hal_channel(channel)) != HAL_OK)
    {
        log_e("DAC禁用失败");
        return DAC_ERROR_HAL;
    }

    log_d("DAC通道%d已禁用", channel);
    return DAC_OK;
}

/**
 * @brief       输出三角波
 *
 * @param[in]   channel   DAC通道
 * @param[in]   amplitude 三角波幅度(0-4095)
 *
 * @retval      DAC_OK         配置成功
 * @retval      DAC_ERROR_PARAM 参数错误
 *
 * @note        使用DAC硬件三角波生成功能
 */
DAC_Error_e dac_output_triangle(DAC_Channel_e channel, uint16_t amplitude)
{
    DAC_ChannelConfTypeDef dac_ch_conf = {0};

    if ((channel == DAC_CH_1 && !sg_dac_ch1_initialized) ||
        (channel == DAC_CH_2 && !sg_dac_ch2_initialized))
    {
        log_e("DAC通道%d未初始化", channel);
        return DAC_ERROR_PARAM;
    }

    /* 配置DAC通道 */
    dac_ch_conf.DAC_Trigger = DAC_TRIGGER_T6_TRGO;             /* TIM6触发 */
    dac_ch_conf.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;

    if (HAL_DAC_ConfigChannel(&sg_dac_handle, &dac_ch_conf, dac_get_hal_channel(channel)) != HAL_OK)
    {
        log_e("DAC通道配置失败");
        return DAC_ERROR_HAL;
    }

    /* 配置三角波生成（STM32F1使用专用函数） */
    if (HAL_DACEx_TriangleWaveGenerate(&sg_dac_handle, dac_get_hal_channel(channel), DAC_TRIANGLEAMPLITUDE_4095) != HAL_OK)
    {
        log_e("三角波配置失败");
        return DAC_ERROR_HAL;
    }

    /* 启动DAC */
    HAL_DAC_Start(&sg_dac_handle, dac_get_hal_channel(channel));

    log_i("DAC通道%d三角波输出已启动", channel);
    return DAC_OK;
}

/**
 * @brief       输出噪声
 *
 * @param[in]   channel DAC通道
 *
 * @retval      DAC_OK         配置成功
 * @retval      DAC_ERROR_PARAM 参数错误
 *
 * @note        使用DAC硬件噪声生成功能
 */
DAC_Error_e dac_output_noise(DAC_Channel_e channel)
{
    DAC_ChannelConfTypeDef dac_ch_conf = {0};

    if ((channel == DAC_CH_1 && !sg_dac_ch1_initialized) ||
        (channel == DAC_CH_2 && !sg_dac_ch2_initialized))
    {
        log_e("DAC通道%d未初始化", channel);
        return DAC_ERROR_PARAM;
    }

    /* 配置DAC通道 */
    dac_ch_conf.DAC_Trigger = DAC_TRIGGER_T6_TRGO;
    dac_ch_conf.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;

    if (HAL_DAC_ConfigChannel(&sg_dac_handle, &dac_ch_conf, dac_get_hal_channel(channel)) != HAL_OK)
    {
        log_e("DAC通道配置失败");
        return DAC_ERROR_HAL;
    }

    /* 配置噪声生成（STM32F1使用专用函数） */
    if (HAL_DACEx_NoiseWaveGenerate(&sg_dac_handle, dac_get_hal_channel(channel), DAC_LFSRUNMASK_BITS11_0) != HAL_OK)
    {
        log_e("噪声配置失败");
        return DAC_ERROR_HAL;
    }

    /* 启动DAC */
    HAL_DAC_Start(&sg_dac_handle, dac_get_hal_channel(channel));

    log_i("DAC通道%d噪声输出已启动", channel);
    return DAC_OK;
}

/**
 * @brief       打印DAC状态（用于调试）
 *
 * @param       无
 *
 * @retval      无
 *
 * @note        显示DAC配置和状态
 */
void dac_print_status(void)
{
    log_i("DAC当前状态:");
    log_i("  通道1: %s", sg_dac_ch1_initialized ? "已初始化" : "未初始化");
    log_i("  通道2: %s", sg_dac_ch2_initialized ? "已初始化" : "未初始化");
    log_i("  分辨率: %d位", DAC_RESOLUTION);
    log_i("  参考电压: %.2fV", DAC_VREF);
}
